package com.company.loganalyzer.tools.impl;

import com.company.loganalyzer.config.ElasticsearchConfig;
import com.company.loganalyzer.dto.ToolInput;
import com.company.loganalyzer.dto.ToolResult;
import com.company.loganalyzer.model.LogEntry;
import com.company.loganalyzer.tools.LogAnalysisTool;
import com.company.loganalyzer.utils.TimeRangeUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.*;

/**
 * 追踪上下文分析工具
 * 
 * 对应Python版本的trace_error_context函数
 * 通过traceId追踪完整的错误上下文和执行流程
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class TraceContextTool implements LogAnalysisTool {

    private final ElasticsearchOperations elasticsearchOperations;
    private final ElasticsearchConfig elasticsearchConfig;

    @Override
    public String getName() {
        return "trace_error_context";
    }

    @Override
    public String getDescription() {
        return "通过traceId追踪完整的错误上下文，分析请求执行流程和错误链路";
    }

    @Override
    public String[] getSupportedParameters() {
        return new String[]{"traceId", "timeRange"};
    }

    @Override
    public boolean canHandle(ToolInput input) {
        String query = input.getQuery();
        return (input.getTraceId() != null && !input.getTraceId().trim().isEmpty()) ||
               (query != null && (query.contains("追踪") || query.contains("trace") || 
                query.contains("链路") || query.contains("上下文")));
    }

    @Override
    public int getPriority() {
        return 15; // 较高优先级
    }

    @Override
    public Mono<ToolResult> execute(ToolInput input) {
        return Mono.fromCallable(() -> {
            long startTime = System.currentTimeMillis();
            
            try {
                String traceId = extractTraceId(input);
                if (traceId == null || traceId.trim().isEmpty()) {
                    return ToolResult.error(getName(), "未提供有效的traceId");
                }
                
                // 构建追踪查询
                NativeSearchQuery searchQuery = buildTraceQuery(traceId, input);
                
                // 设置索引名称
                List<String> indexNames = TimeRangeUtils.generateIndexNames(
                    elasticsearchConfig.getIndexPattern(), 
                    input.getTimeRange()
                );
                
                // 执行搜索
                SearchHits<LogEntry> searchHits = elasticsearchOperations.search(
                    searchQuery, 
                    LogEntry.class,
                    indexNames.toArray(new String[0])
                );
                
                // 处理结果
                List<LogEntry> traceLogs = searchHits.getSearchHits().stream()
                    .map(SearchHit::getContent)
                    .collect(Collectors.toList());
                
                if (traceLogs.isEmpty()) {
                    return ToolResult.error(getName(), "未找到traceId为 " + traceId + " 的日志记录");
                }
                
                // 分析追踪上下文
                Map<String, Object> contextAnalysis = analyzeTraceContext(traceLogs, traceId);
                
                // 构建返回结果
                Map<String, Object> result = new HashMap<>();
                result.put("traceId", traceId);
                result.put("timeRange", input.getTimeRange());
                result.put("totalLogs", traceLogs.size());
                result.put("contextAnalysis", contextAnalysis);
                result.put("traceLogs", traceLogs);
                result.put("indexNames", indexNames);
                
                long executionTime = System.currentTimeMillis() - startTime;
                
                log.info("追踪分析完成 - traceId: {}, 时间范围: {}, 日志数: {}, 耗时: {}ms", 
                    traceId, input.getTimeRange(), traceLogs.size(), executionTime);
                
                ToolResult toolResult = ToolResult.success(getName(), result, "追踪分析完成");
                toolResult.setExecutionTime(executionTime);
                return toolResult;
                
            } catch (Exception e) {
                log.error("追踪分析失败", e);
                return ToolResult.error(getName(), "追踪分析失败: " + e.getMessage(), e);
            }
        });
    }

    /**
     * 提取traceId
     */
    private String extractTraceId(ToolInput input) {
        // 优先使用直接提供的traceId
        if (input.getTraceId() != null && !input.getTraceId().trim().isEmpty()) {
            return input.getTraceId().trim();
        }
        
        // 从query中提取traceId
        String query = input.getQuery();
        if (query != null) {
            // 尝试匹配常见的traceId格式
            String[] patterns = {
                "traceId[=:]\\s*([a-zA-Z0-9-]+)",
                "trace[=:]\\s*([a-zA-Z0-9-]+)",
                "追踪[ID|id][=:]\\s*([a-zA-Z0-9-]+)",
                "([a-zA-Z0-9]{8,32})" // 通用的ID格式
            };
            
            for (String pattern : patterns) {
                java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern);
                java.util.regex.Matcher m = p.matcher(query);
                if (m.find()) {
                    return m.group(1);
                }
            }
        }
        
        return null;
    }

    /**
     * 构建追踪查询
     */
    private NativeSearchQuery buildTraceQuery(String traceId, ToolInput input) {
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        
        var boolQuery = boolQuery();
        
        // traceId过滤
        boolQuery.filter(termQuery("traceId", traceId));
        
        // 时间范围过滤
        if (input.getTimeRange() != null) {
            LocalDateTime[] timeRange = TimeRangeUtils.parseTimeRange(input.getTimeRange());
            boolQuery.filter(rangeQuery("timestamp")
                .gte(timeRange[0])
                .lte(timeRange[1]));
        }
        
        queryBuilder.withQuery(boolQuery);
        
        // 按时间正序排列，展示完整的执行流程
        queryBuilder.withSort(Sort.by(Sort.Direction.ASC, "timestamp"));
        
        // 限制最大500条，避免数据过多
        queryBuilder.withMaxResults(500);
        
        return queryBuilder.build();
    }

    /**
     * 分析追踪上下文
     */
    private Map<String, Object> analyzeTraceContext(List<LogEntry> traceLogs, String traceId) {
        Map<String, Object> analysis = new HashMap<>();
        
        // 按时间排序（确保顺序正确）
        List<LogEntry> sortedLogs = traceLogs.stream()
            .sorted(Comparator.comparing(LogEntry::getTimestamp))
            .collect(Collectors.toList());
        
        // 1. 执行流程分析
        List<Map<String, Object>> executionFlow = analyzeExecutionFlow(sortedLogs);
        analysis.put("executionFlow", executionFlow);
        
        // 2. 错误分析
        List<Map<String, Object>> errors = analyzeErrors(sortedLogs);
        analysis.put("errors", errors);
        
        // 3. 服务调用链分析
        Map<String, Object> serviceChain = analyzeServiceChain(sortedLogs);
        analysis.put("serviceChain", serviceChain);
        
        // 4. 性能分析
        Map<String, Object> performance = analyzePerformance(sortedLogs);
        analysis.put("performance", performance);
        
        // 5. 异常传播路径
        List<String> exceptionPath = analyzeExceptionPath(sortedLogs);
        analysis.put("exceptionPath", exceptionPath);
        
        // 6. 总结信息
        Map<String, Object> summary = generateSummary(sortedLogs, traceId);
        analysis.put("summary", summary);
        
        return analysis;
    }

    /**
     * 分析执行流程
     */
    private List<Map<String, Object>> analyzeExecutionFlow(List<LogEntry> sortedLogs) {
        List<Map<String, Object>> flow = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
        
        for (int i = 0; i < sortedLogs.size(); i++) {
            LogEntry log = sortedLogs.get(i);
            Map<String, Object> step = new HashMap<>();
            
            step.put("step", i + 1);
            step.put("timestamp", log.getTimestamp().format(formatter));
            step.put("service", log.getServiceName() != null ? log.getServiceName() : "UNKNOWN");
            step.put("level", log.getLevel());
            step.put("message", truncateMessage(log.getMessage(), 150));
            step.put("threadId", log.getThreadId());
            
            // 标记关键步骤
            if (log.getLevel() != null) {
                switch (log.getLevel()) {
                    case "ERROR":
                    case "FATAL":
                    case "CRITICAL":
                        step.put("type", "ERROR");
                        step.put("critical", true);
                        break;
                    case "WARN":
                        step.put("type", "WARNING");
                        break;
                    default:
                        step.put("type", "NORMAL");
                }
            }
            
            // 计算步骤间隔时间
            if (i > 0) {
                LocalDateTime prevTime = sortedLogs.get(i - 1).getTimestamp();
                LocalDateTime currentTime = log.getTimestamp();
                long intervalMs = java.time.Duration.between(prevTime, currentTime).toMillis();
                step.put("intervalMs", intervalMs);
                
                if (intervalMs > 1000) { // 超过1秒的步骤标记为慢操作
                    step.put("slow", true);
                }
            }
            
            flow.add(step);
        }
        
        return flow;
    }

    /**
     * 分析错误信息
     */
    private List<Map<String, Object>> analyzeErrors(List<LogEntry> sortedLogs) {
        List<Map<String, Object>> errors = new ArrayList<>();
        
        for (LogEntry log : sortedLogs) {
            if (log.getLevel() != null && 
                Arrays.asList("ERROR", "FATAL", "CRITICAL").contains(log.getLevel())) {
                
                Map<String, Object> error = new HashMap<>();
                error.put("timestamp", log.getTimestamp().toString());
                error.put("service", log.getServiceName());
                error.put("level", log.getLevel());
                error.put("message", log.getMessage());
                error.put("exception", log.getException());
                error.put("threadId", log.getThreadId());
                
                // 错误分类
                String errorType = classifyError(log);
                error.put("errorType", errorType);
                
                errors.add(error);
            }
        }
        
        return errors;
    }

    /**
     * 分析服务调用链
     */
    private Map<String, Object> analyzeServiceChain(List<LogEntry> sortedLogs) {
        Map<String, Object> serviceChain = new HashMap<>();
        
        // 涉及的服务列表
        Set<String> services = sortedLogs.stream()
            .map(log -> log.getServiceName() != null ? log.getServiceName() : "UNKNOWN")
            .collect(Collectors.toCollection(LinkedHashSet::new));
        
        serviceChain.put("servicesInvolved", new ArrayList<>(services));
        serviceChain.put("serviceCount", services.size());
        
        // 服务调用顺序
        List<String> callSequence = sortedLogs.stream()
            .map(log -> log.getServiceName() != null ? log.getServiceName() : "UNKNOWN")
            .distinct()
            .collect(Collectors.toList());
        
        serviceChain.put("callSequence", callSequence);
        
        // 各服务的日志数量
        Map<String, Long> serviceLogCounts = sortedLogs.stream()
            .collect(Collectors.groupingBy(
                log -> log.getServiceName() != null ? log.getServiceName() : "UNKNOWN",
                Collectors.counting()
            ));
        
        serviceChain.put("serviceLogCounts", serviceLogCounts);
        
        return serviceChain;
    }

    /**
     * 分析性能指标
     */
    private Map<String, Object> analyzePerformance(List<LogEntry> sortedLogs) {
        Map<String, Object> performance = new HashMap<>();
        
        if (sortedLogs.size() < 2) {
            performance.put("totalDuration", 0);
            return performance;
        }
        
        LocalDateTime startTime = sortedLogs.get(0).getTimestamp();
        LocalDateTime endTime = sortedLogs.get(sortedLogs.size() - 1).getTimestamp();
        
        long totalDurationMs = java.time.Duration.between(startTime, endTime).toMillis();
        performance.put("totalDuration", totalDurationMs + "ms");
        performance.put("startTime", startTime.toString());
        performance.put("endTime", endTime.toString());
        
        // 计算各阶段耗时
        List<Long> stepDurations = new ArrayList<>();
        for (int i = 1; i < sortedLogs.size(); i++) {
            LocalDateTime prev = sortedLogs.get(i - 1).getTimestamp();
            LocalDateTime current = sortedLogs.get(i).getTimestamp();
            stepDurations.add(java.time.Duration.between(prev, current).toMillis());
        }
        
        if (!stepDurations.isEmpty()) {
            performance.put("averageStepDuration", 
                stepDurations.stream().mapToLong(Long::longValue).average().orElse(0) + "ms");
            performance.put("maxStepDuration", 
                stepDurations.stream().mapToLong(Long::longValue).max().orElse(0) + "ms");
        }
        
        // 性能评估
        String performanceLevel;
        if (totalDurationMs < 1000) {
            performanceLevel = "优秀";
        } else if (totalDurationMs < 5000) {
            performanceLevel = "良好";
        } else if (totalDurationMs < 10000) {
            performanceLevel = "一般";
        } else {
            performanceLevel = "需要优化";
        }
        performance.put("performanceLevel", performanceLevel);
        
        return performance;
    }

    /**
     * 分析异常传播路径
     */
    private List<String> analyzeExceptionPath(List<LogEntry> sortedLogs) {
        List<String> path = new ArrayList<>();
        
        for (LogEntry log : sortedLogs) {
            if (log.getLevel() != null && 
                Arrays.asList("ERROR", "FATAL", "CRITICAL").contains(log.getLevel())) {
                
                String pathStep = String.format("%s -> %s: %s", 
                    log.getTimestamp().format(DateTimeFormatter.ofPattern("HH:mm:ss")),
                    log.getServiceName() != null ? log.getServiceName() : "UNKNOWN",
                    truncateMessage(log.getMessage(), 80));
                
                path.add(pathStep);
            }
        }
        
        return path;
    }

    /**
     * 生成总结信息
     */
    private Map<String, Object> generateSummary(List<LogEntry> sortedLogs, String traceId) {
        Map<String, Object> summary = new HashMap<>();
        
        summary.put("traceId", traceId);
        summary.put("totalSteps", sortedLogs.size());
        
        // 错误统计
        long errorCount = sortedLogs.stream()
            .mapToLong(log -> {
                String level = log.getLevel();
                return (level != null && Arrays.asList("ERROR", "FATAL", "CRITICAL").contains(level)) ? 1 : 0;
            })
            .sum();
        
        summary.put("errorCount", errorCount);
        summary.put("hasErrors", errorCount > 0);
        
        // 状态评估
        String status;
        if (errorCount == 0) {
            status = "成功";
        } else if (errorCount == 1) {
            status = "部分失败";
        } else {
            status = "失败";
        }
        summary.put("status", status);
        
        // 主要问题
        if (errorCount > 0) {
            LogEntry firstError = sortedLogs.stream()
                .filter(log -> log.getLevel() != null && 
                    Arrays.asList("ERROR", "FATAL", "CRITICAL").contains(log.getLevel()))
                .findFirst()
                .orElse(null);
            
            if (firstError != null) {
                summary.put("firstError", Map.of(
                    "service", firstError.getServiceName(),
                    "message", truncateMessage(firstError.getMessage(), 100),
                    "timestamp", firstError.getTimestamp().toString()
                ));
            }
        }
        
        return summary;
    }

    /**
     * 错误分类
     */
    private String classifyError(LogEntry log) {
        String message = log.getMessage();
        String exception = log.getException();
        String text = (message != null ? message : "") + " " + (exception != null ? exception : "");
        
        if (text.contains("NullPointerException")) {
            return "空指针异常";
        } else if (text.contains("TimeoutException") || text.contains("timeout")) {
            return "超时异常";
        } else if (text.contains("ConnectionException") || text.contains("connection")) {
            return "连接异常";
        } else if (text.contains("SQLException")) {
            return "数据库异常";
        } else if (text.contains("IllegalArgumentException")) {
            return "参数异常";
        } else {
            return "其他异常";
        }
    }

    /**
     * 截断消息
     */
    private String truncateMessage(String message, int maxLength) {
        if (message == null) return "";
        if (message.length() <= maxLength) return message;
        return message.substring(0, maxLength) + "...";
    }
}